[OpenBSD] OpenSSH jako serwer SFTP czyli bezpieczny serwer plików

Kategoria: FAQ, etykiety: openbsd, openssh, sftp, serwer plików

Dodany: 2016-08-04 22:58 (zmodyfikowany: 2016-09-25 16:16)
Przez: uzytkownikubunt

Wyświetleń: 25706

Wersja oprogramowania

Poradnik pisany wobec serwera OpenSSH, w wersji 7.3, uruchomionego w rozwojowej wersji systemu OpenBSD-current (sierpień 2016).

Co przedstawia poradnik

Poradnik pokazuje jak dla dwóch określonych użytkowników (Andrzej, Magda, a w zasadzie odpowiednio: _ssh_andrzej, _ssh_magda), których rozróżnimy za pomocą używanych przez nich kluczy, pozwolić na dostęp do serwera plików SFTP (zapis, odczyt, zmiana uprawnień) bez możliwości uruchamiania komend. Istnieje możliwość innego ustawienia ścieżki chrootowania i dzięki temu również izolacji kont użytkowników SFTP między sobą, ale to odebrałoby możliwość udostępniania swoich plików (w swoim katalogu przez zmianę uprawnień) innym użytkownikom. Użytkownicy będą mogli edytować również listę swoich kluczy publicznych. Można by tę możliwość uniemożliwić umiejscawiając te pliki poza chrootem i/lub nadająć odpowiednie uprawnienia i flagi na pliku. Poza nimi do serwera będzie mógł się zalogować klient _ssh_default też autoryzując się przez klucz, ale nie posiadająć uprawnień do modyfikacji i zapisu plików, katalogów. Użytkownicy Andrzej i Magda również będą widzieć zawartość katalogu użytkownika _ssh_default. Poradnik skupia się na części serwerowej. Serwer będzie uruchomiony na adresie pętli lokalnej 127.0.0.1, więc trzeba go zmienić, jeśli się chce go udostępnić w sieci lokalnej lub Internecie.

Jak zwiększyć swoją wiedzę korzystając z tego poradnika

Osobom chcącym z niego skorzystać proponuję poczytać w manual-u co oznaczają poszczególne polecenia i parametry podane do nich, gdyż większości nie opisałem. Manual można znaleźć korzystając z polecenia man lub czytać online w przeglądarce. Druga opcja jest szczególnie przydatna osobom nie posiadającym zainstalowanego systemu OpenBSD. Osoby korzystające z Gnu/Linuksa (np Debiana) powinny niestety porównać znaczenie opcji w manualu zarówno systemu OpenBSD jak i np Debiana. Obecnie manual OpenBSD znajduje się pod adresem: http://man.openbsd.org/ lub wpisując man w terminalu/konsoli.

Jeśli czytasz manual, a i tak czegoś nie jesteś pewna(y) to oczywiście można zapytać tutaj na forum.

Kilka słów o protokołach FTP, FTPS, SFTP

Protokół FTP służy do przesyłania plików między klientem a serwerem. Powstawał w czasach krystalizowania się stosu TCP/IP i wymaga archaicznych rozwiązań m.in. otwierania dwóch połączeń TCP między klientem a serwerem. Zdefiniowane są dwa tryby, z czego jeden wymaga otwarcia w kliencie portu na firewallu, a drugi wymaga otwarcia szeregu portów na serwerze. Mocno utrudniają one tworzenie sensownej polityki firewalla. FTP sam w sobie nie zapewnia bezpieczeństwa tj szyfrowania, autoryzacji z użyciem kryptografi. W późniejszym czasie stworzono rozszerzenie protokołu FTP w postaci FTPS, które dodaje szyfrowanie i autoryzację, ale dalej nie jest to najlepsze rozwiązanie. Dodatkowo szyfrowanie utrudnia możliwość dynamicznego otwierania portów na firewallu, co było jednym z rozwiązań wcześniej wspomnianych problemów z trybami i połączeniami TCP.

Na szczęście istnieje protokół SFTP. Jest to protokół z punktu widzenia osoby używającej klienta podobny do FTP, lecz działający z użyciem jednego, stałego portu i od początku projektowany jako bezpieczny (m.in. tunelowany w bezpiecznym połączeniu np protokołu SSH).

Zabezpieczenia

Zabezpieczenie danych między kontami na serwerze opiera się na tradycyjnych Uniksowych uprawnieniach do plików. Użytkownicy powinni więc sami uważać z jakimi uprawnieniami tworzą pliki. Procesy użytkowników będą zchrootowane, co w połączeniu ze zrzucaniem uprawnień przez proces powinno ochronić przed dostępem do reszty drzewa katalogów. Komenda sftp jest wymuszana w konfiguracji, co oznacza odebranie prawa do innych komend. Innymi słowy nie można korzystać z shella. Niestety nie jest ograniczony rozmiar plików i całkowita objętość wszystkich plików. Najbezpieczniej byłoby podmontować /mnt/chroots/ jako oddzielny system plików i dodać dodatkową ochronę przed złośliwym zapełnieniem za pomocą quota'y i ograniczenia maksymalnego rozmiaru pliku. Jeśli jednak założymy, że użytkownicy są w miarę zaufani i nie będą próbować szkodzić serwerowi (np znajomi albo to osobisty serwer) to serwer jest całkiem bezpieczny. Dane użytkownika będą dosyć bezpieczne jeśli będzie chronił swój klucz prywatny i nie nadawał na swoich plikach zbyt luźnych uprawnień. Oprócz tego przydałby się proaktywny firewall potrafiący zablokować hosty po IP w czasie prób skanowania portów i wielokrotnych połączeniach w krótkim czasie do serwera OpenSSH. Możnaby pokusić się również o zwiększenie logowanych informacji o działaniach użytkowników.

Last but not least: Oczywiście dalej ważne jest w odpowiednio krótkim czasie instalowanie zaaktualizowanej wersji oprogramowania, by łatać publicznie znane dziury.

OpenBSD a wydajność dostępu (odczyt, zapis) do dużych ilości danych w postaci plików

Złożone projekty, które są dostępne na rynku, zwykle mają zarówno mocne jak i słabe strony. Tak też jest z OpenBSD. Niestety system plików (FFS) jak i podsystem pamięci masowej w systemie OpenBSD jest relatywnie słabą stroną systemu. System plików jest dosyć prymitywny. W innych systemach operacyjnych pamięć podręczna systemu operacyjnego potrafi dosyć wydatnie zwiększyć wydajność odczytu i zapisu na dysk, a w OpenBSD nie jest to zbyt skuteczne. Plusem dla tej części systemu operacyjnego to stabilność systemu plików. Istnieje też możliwość skorzystania z programowego RAID-a wbudowanego w OpenBSD. W przypadku prostego serwera dla siebie i znajomych ograniczenia nie powinny dać się we znaki, ale w przypadku tworzenia bardziej obciążanego (pod względem ilości danych, rządań zapisu i odczytu) serwera warto zastanowić się nad wyborem innego systemu operacyjnego np FreeBSD z systemem plików ZFS.

Niestety nie wszystkie zabezpieczenia przed włamaniami, wbudowane w OpenSSH (mam namyśli separację procesów, zadań i przywilejów - z ang. Privilege separation), nie zawsze na innych systemach operacyjnych działają tak poprawnie jak w systemie OpenBSD.

Do dzieła

Dane będą przechowywane w podkatalogach /mnt/chroots/sftp/home/. Zakładam, że mogę zmieniać uprawnienia /chroots, bo tam jeszcze nie ma innych podkatalogów.

mkdir -p /mnt/chroots/sftp/home/

Tworzymy grupę zbiorczą dla wszystkich użytkowników logujących się do sftp:

groupadd _ssh_wszyscy

Nadajemy uprawniania:

chown    root:wheel /mnt/chroots
# R oznacza nadanie uprawnień wszystkim podfolderom i plikom w nich. P oznacza nie podążanie za żadnym symlinkami.
chown -RP root:_ssh_wszyscy /mnt/chroots/sftp/
chmod -RP 640 /mnt/chroots
chmod    1600 /mnt/chroots/sftp/
# Na katalogach, i tylko dla nich, nadajemy uprawnienia właścicielowi i grupie, by mogli do nich wchodzić
find /mnt/chroots/ -type d -exec chmod ug+x {} \;
chmod     o+x /mnt/chroots
# Odpowiednik Gnu/Linuksowego chattr +a
chflags uappnd /mnt/chroots/sftp

Na początku tworzone są katalogi użytkowników i plik name, który w łatwy sposób pozwoli zorientować się jako kto są zalogowani.

mkdir -p /mnt/chroots/sftp/home/ssh_andrzej
mkdir -p /mnt/chroots/sftp/home/ssh_magda   
mkdir -p /mnt/chroots/sftp/home/ssh_shared_ro
echo "Andrzej" > /mnt/chroots/sftp/home/ssh_andrzej/name                                  
echo "Magda"   > /mnt/chroots/sftp/home/ssh_magda/name                                      
echo "Domyślny"> /mnt/chroots/sftp/home/ssh_shared_ro/name

Oprócz tego można też wrzucić plik fałszywej powłoki wewnątrz chroota

mkdir -p /mnt/chroots/sftp/bin
ln -s /bin/date  /mnt/chroots/sftp/bin/date
chown -RP root:wheel /mnt/chroots/sftp/bin/
chmod a+x            /mnt/chroots/sftp/bin/
chmod 511            /mnt/chroots/sftp/bin/date

Tworzymy konta użytkowników, ustawiamy fake'owego shella, dodajemy użytkowników do zbiorczej grupy _ssh_wszyscy:

useradd -d /mnt/chroots/sftp/home/ssh_shared_ro -G _ssh_wszyscy -e 0  -s /bin/date  _ssh_default
useradd -d /mnt/chroots/sftp/home/ssh_andrzej   -G _ssh_wszyscy -e 0  -s /bin/date  _ssh_andrzej
useradd -d /mnt/chroots/sftp/home/ssh_magda     -G _ssh_wszyscy -e 0  -s /bin/date  _ssh_magda

Nadajemy uprawnienia katalogom:

chown -RP         root:_ssh_wszyscy /mnt/chroots/sftp/home/ssh_shared_ro
chown -RP _ssh_andrzej:_ssh_andrzej /mnt/chroots/sftp/home/ssh_andrzej
chown -RP _ssh_magda:_ssh_magda     /mnt/chroots/sftp/home/ssh_magda
chmod -RP  600 /mnt/chroots/sftp/home/ssh_andrzej
chmod -RP  600 /mnt/chroots/sftp/home/ssh_magda
chmod -RP  440 /mnt/chroots/sftp/home/ssh_shared_ro
find /mnt/chroots/sftp/home -type d -exec chmod ug+x {} \;
chmod +t      /mnt/chroots/sftp/home/ssh_shared_ro
# uchg to słabszy odpowiednik Gnu/Linuksowego chattr +i. schg to mocniejsza wersja chattr +i.
chflags uchg   /mnt/chroots/sftp/home/ssh_shared_ro/name
chmod +t       /mnt/chroots/sftp/home
chflags uappnd /mnt/chroots/sftp/home/

Tworzenie kluczy dla hosta W tym celu tworzymy tymczasowy katalog. Warto pamiętać, że /tmp jest zwykle czyszczone podczas restartu.

mkdir -p       /tmp/klucze_ssh
chown -RP root /tmp/klucze_ssh
chmod -RP 600  /tmp/klucze_ssh    
cd /tmp/klucze_ssh

Właściwa część tworzenia kluczy. Dla hosta zawsze bez hasła

ssh-keygen -f ssh_host_ed25519_key -o -t ed25519
ssh-keygen -b 3072 -f ssh_host_rsa_key -o -t rsa

Klucze należy przenieść do miejsca, w którym będzie ich szukał serwer OpenSSH. Skopiowanie i nadanie uprawnień.

cp ssh_host_*[key,pub] /etc/ssh/
chown root:wheel /etc/ssh/ssh_host_*[key,pub]
chmod 600        /etc/ssh/ssh_host_*[key,pub]

Tworzenie kluczy dla użytkowników Dla uproszczenia też stworzyłem bez hasła

ssh-keygen -C andrzej -f ssh_id_andrzej_ed25519_key     -o -t ed25519
ssh-keygen -C andrzej -b 3072 -f ssh_id_andrzej_rsa_key -o -t rsa
ssh-keygen -C magda   -f ssh_id_magda_ed25519_key       -o -t ed25519
ssh-keygen -C magda   -b 3072 -f ssh_id_magda_rsa_key   -o -t rsa
ssh-keygen -C default -f ssh_id_default_ed25519_key     -o -t ed25519
ssh-keygen -C default -b 3072 -f ssh_id_default_rsa_key -o -t rsa

Stworzone zostały klucze publiczne i prywatne w typach rsa i ed25519. Daje to 4 pliki na użytkownika. Po podanych komendach stworzone zostanie łącznie 12 plików.

Pliki z końcówką .pub to pliki publiczne. Należy je wrzucić do podkatalogu ~/.ssh/authorized_keys2 w katalogach domowych użytkowników na serwerze.

mkdir -p /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/
mkdir -p /mnt/chroots/sftp/home/ssh_magda/\.ssh/
mkdir -p /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/

Dopisujemy klucze

Restrict wyłącza forwardowanie itp, ale opcje w sshd_config mają pierszeństwo. Poza tym użytkownicy Andrzej i Magda mogą zmieniać własne pliki, również authorized_keys2, więc mogą usunąć restrict.

awk '{printf "restrict ";print $0}' ssh_id_andrzej_*pub > /mnt/chroots/sftp/home/ssh_andrzej/.ssh/authorized_keys2
awk '{printf "restrict ";print $0}' ssh_id_magda_*pub   > /mnt/chroots/sftp/home/ssh_magda/.ssh/authorized_keys2
awk '{printf "restrict ";print $0}' ssh_id_default_*_key.pub > /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/authorized_keys2

Zmieniamy uprawnienia:

chown -RP _ssh_andrzej:_ssh_andrzej /mnt/chroots/sftp/home/ssh_andrzej/.ssh/
chown -RP _ssh_magda:_ssh_magda     /mnt/chroots/sftp/home/ssh_magda/.ssh/
chown -RP _ssh_default:_ssh_default /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chmod   600  /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/authorized_keys2
chmod   600  /mnt/chroots/sftp/home/ssh_magda/\.ssh/authorized_keys2
chmod   400  /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/authorized_keys2
# uchg to słabszy odpowiednik Gnu/Linuksowego chattr +i. schg to mocniejsza wersja chattr +i.
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/\.ssh/authorized_keys2
chmod   700  /mnt/chroots/sftp/home/ssh_andrzej/\.ssh/
chmod   700  /mnt/chroots/sftp/home/ssh_magda/\.ssh/
chmod  1500  /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro
chflags uchg /mnt/chroots/sftp/home/ssh_shared_ro/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_magda/.ssh/
chflags uchg /mnt/chroots/sftp/home/ssh_andrzej/.ssh/

Możemy przenieść klucze prywatne do klienta

Pliki bez końcówki pub (czyli kończące się na key) to klucze prywatne. Należy je w bezpieczny sposób przenieść na klienta do podkatalogu ~/.ssh/ w katalogu domowym użytkownika do plików id_rsa i id_ed25519.

Zakładając, że testujemy i mamy klienta na tym samym komputerze co serwer, testowy klient ma być uruchomiony na koncie użytkownika test i chcemy mięć dostęp do serwera z poziomu użytkownika default, plik klucza prywatnego typu ed25519 przeniesiemy poleceniami:

cp ssh_id_default_ed25519_key /home/test/.ssh/id_ed25519 
chown test:test /home/test/.ssh/id_ed25519               
chmod 600 /home/test/.ssh/id_ed25519

Podobnie z kluczami publicznymi:

cp ssh_id_default_ed25519_key.pub /home/test/.ssh/id_ed25519.pub
chown test:test /home/test/.ssh/id_ed25519.pub               
chmod 600 /home/test/.ssh/id_ed25519.pub

Przenieśliśmy klucze typu ed25519. Analogicznie przenosimy klucze RSA.

Zawartość wklejana do pliku konfiguracji

Główny plik konfiguracji ma domyślną ścieżkę /etc/ssh/sshd_config. Jego zmiana jednak na nasz spowoduje uruchomienie tylko i wyłącznie SFTP, czyli nie można będzie zalogować się i wydawać komend! Jeśli masz zdalny serwer prawdopodobnie chcesz stworzyć inną usługę sshd i wgrać konfigurację dla niej pod inną ścieżką (by nie utracić zdalnego dostępu do serwera), ale w tym poradniku dla uproszczenia ustawiam go jako /etc/ssh/sshd_config.

ListenAddress 127.0.0.1
AllowGroups _ssh_wszyscy
#
ChallengeResponseAuthentication no
ClientAliveCountMax 1
ClientAliveInterval 15
Compression yes
Ciphers chacha20-poly1305@openssh.com,aes128-gcm@openssh.com,aes256-gcm@openssh.com
HostKeyAlgorithms ssh-ed25519,ssh-rsa
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com
PubkeyAcceptedKeyTypes ssh-ed25519,ssh-rsa
IPQoS throughput
KbdInteractiveAuthentication no
PasswordAuthentication no
LoginGraceTime 10
MaxAuthTries 2
MaxSessions 3
MaxStartups 2
PermitTunnel no
PermitUserEnvironment no
PermitUserRC no
X11Forwarding no
StrictModes yes
AuthorizedKeysFile "%h/.ssh/authorized_keys2"
HostKey /etc/ssh/ssh_host_ed25519_key
HostKey /etc/ssh/ssh_host_rsa_key
AllowAgentForwarding no
AllowTcpForwarding no
AllowStreamLocalForwarding no
PermitTTY no
PermitRootLogin no
UsePrivilegeSeparation sandbox

Subsystem       sftp    internal-sftp

ChrootDirectory /mnt/chroots/sftp/
ForceCommand internal-sftp -R -d /home/ssh_shared_ro

Match User _ssh_andrzej
    ForceCommand internal-sftp -d /home/ssh_andrzej  -u 007

Match User _ssh_magda
    ForceCommand internal-sftp -d /home/ssh_magda    -u 007

Po tym można zrestartować sshd:

rcctl -f restart sshd

I sprawdzić jego stan:

rcctl check sshd                                                             

Połączenie klienta do serwera SFTP

Aby użytkownik test na komputerze kliencie mógł uwierzytalnić się jako inny użytkownik, z użyciem kluczy prywatnych z jego podkatalogu ~/.ssh/, należy użyć komendy:

sftp -i /home/test/.ssh/id_ed25519  _ssh_default@127.0.0.1

OSnews Wykop Blip Flaker Kciuk Śledzik Facebook Identi.ca Twitter del.icio.us Google Bookmarks